package com.itheima.app.manager;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.itheima.app.interceptor.UserHolder;
import com.itheima.app.log.LogWith;
import com.itheima.app.mq.MovementScoreMQSend;
import com.itheima.autoconfig.oss.OssTemplate;
import com.itheima.domain.db.UserInfo;
import com.itheima.domain.mongo.Comment;
import com.itheima.domain.mongo.Movement;
import com.itheima.service.db.UserInfoService;
import com.itheima.service.mongo.CommentService;
import com.itheima.service.mongo.MovementService;
import com.itheima.util.ConstantUtil;
import com.itheima.vo.CommentVo;
import com.itheima.vo.MovementVo;
import com.itheima.vo.PageBeanVo;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Component
public class MovementManager {

    @DubboReference
    private MovementService movementService;

    @Autowired
    private OssTemplate ossTemplate;

    @DubboReference
    private UserInfoService userInfoService;

    @DubboReference
    private CommentService commentService;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    @Autowired
    private MovementScoreMQSend movementScoreMQSend;

    // 发布动态
    public void saveMovement(Movement movement, MultipartFile[] imageContent) throws IOException {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.上传图片到oss
        List<String> medias = new ArrayList<>();
        if (ArrayUtil.isNotEmpty(imageContent)) {
            for (MultipartFile multipartFile : imageContent) {
                String picUrl = ossTemplate.upload(multipartFile.getOriginalFilename(), multipartFile.getInputStream());
                medias.add(picUrl);
            }
        }
        // 3.封装完善movement对象
        movement.setId(ObjectId.get()); // 主键id
        movement.setUserId(userId); // 用户id
        movement.setMedias(medias); // 动态图片
        movement.setState(0); // 待审核
        movement.setCreated(System.currentTimeMillis());
        movement.setSeeType(1); // 目前1.0V 是写死的



        // 发的动态id到mq中
        rocketMQTemplate.convertAndSend("tanhua-movement-check", movement.getId().toHexString());

        // 发动推荐动态到mq
        movementScoreMQSend.sendMovementScore(userId, movement.getId(), MovementScoreMQSend.MOVEMENT_PUBLISH);

        // 4.调用rpc发布动态
        movementService.saveMovement(movement);

    }

    // 查看我的动态
    @LogWith(type = "0202")
    public ResponseEntity findMyMovement(Long userId, Integer pageNum, Integer pageSize) {
        // 1.调用rpc查询个人动态分页对象
        PageBeanVo pageBeanVo = movementService.findMyMovement(userId, pageNum, pageSize);
        // 2.封装movementVo
        // 2-1 声明vo集合
        List<MovementVo> voList = new ArrayList<>();
        // 2-2 取出动态详情集合
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        // 2-3 遍历动态详情集合
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                // 查询动态发布人的信息
                UserInfo userInfo = userInfoService.findById(movement.getUserId());
                // 封装vo对象
                MovementVo vo = new MovementVo();
                // 注意顺序问题  先userInfo  再 movement
                vo.setUserInfo(userInfo); // 用户信息
                vo.setUserId(movement.getUserId()); // 用户id
                vo.setMovement(movement); // 动态详情

                // 处理当前是否对此动态点赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, movement.getId(), UserHolder.get().getId()))) {
                    vo.setHasLiked(1);
                }

                // 处理当前是否对此动态喜欢
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, movement.getId(), UserHolder.get().getId()))) {
                    vo.setHasLoved(1);
                }

                // 添加到vo集合中
                voList.add(vo);

            }
        }

        // 3.将vo设置到分页对象中
        pageBeanVo.setItems(voList);

        // 4.返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    // 查看好友动态
    public ResponseEntity findFriendMovement(Integer pageNum, Integer pageSize) {
        // 1.获取线程内的userId
        Long userId = UserHolder.get().getId();
        // 2.调用rpc查询好友动态分页对象
        PageBeanVo pageBeanVo = movementService.findFriendMovement(userId, pageNum, pageSize);
        // 3.封装movementVo
        // 3-1 声明ov集合
        List<MovementVo> voList = new ArrayList<>();
        // 3-2 取出动态详情集合
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        // 3-3 遍历动态详情
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                // 查询发布此动态的用户信息
                UserInfo userInfo = userInfoService.findById(movement.getUserId());

                // 创建vo
                MovementVo movementVo = new MovementVo();
                // 先封装userInfo  再封装movement
                movementVo.setUserInfo(userInfo); // 发布动态的用户信息
                movementVo.setUserId(movement.getUserId()); // 发布动态的用户id
                movementVo.setMovement(movement); // 动态详情

                // 处理当前是否对此动态点赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, movement.getId(), userId))) {
                    movementVo.setHasLiked(1);
                }


                // 将vo添加到集合中
                voList.add(movementVo);
            }
        }

        // 4.将vo设置到分页对象中
        pageBeanVo.setItems(voList);

        // 5.返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    // 查看推荐动态
    public ResponseEntity findRecommendMovement(Integer pageNum, Integer pageSize) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.调用rpc查询推荐动态分页对象
        PageBeanVo pageBeanVo = movementService.findRecommendMovement(userId, pageNum, pageSize);
        // 3.封装movementVo
        // 3-1 声明 vo集合
        List<MovementVo> voList = new ArrayList<>();
        // 3-2 取出动态详情集合
        List<Movement> movementList = (List<Movement>) pageBeanVo.getItems();
        // 3-3 遍历
        if (CollectionUtil.isNotEmpty(movementList)) {
            for (Movement movement : movementList) {
                // 查询发布动态的用户信息
                UserInfo userInfo = userInfoService.findById(movement.getUserId());

                // 创建vo
                MovementVo movementVo = new MovementVo();
                movementVo.setUserInfo(userInfo); // 用户信息
                movementVo.setMovement(movement); // 动态详情

                // 处理当前是否对此动态点赞
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, movement.getId(), userId))) {
                    movementVo.setHasLiked(1);
                }

                // 处理当前是否对此动态喜欢
                if (stringRedisTemplate.hasKey(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, movement.getId(), userId))) {
                    movementVo.setHasLoved(1);
                }

                // 添加到vo集合
                voList.add(movementVo);
            }
        }
        // 4.将vo设置到分页对象
        pageBeanVo.setItems(voList);

        // 5.返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    // 动态点赞
    public ResponseEntity setMovementLike(String publishId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis()); // 发表时间
        comment.setPublishId(new ObjectId(publishId)); // 动态id
        comment.setCommentType(1); // 操作类型：点赞
        comment.setUserId(userId); // 操作人
        // 查询动态详情
        Movement movement = movementService.findById(comment.getPublishId());
        comment.setPublishUserId(movement.getUserId()); // 动态发布人
        // 3.调用rpc点赞保存
        Integer likeCount = commentService.saveComment(comment);
        // 4.将点赞高亮标记存储redis
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, publishId, userId), "1");

        // 发动推荐动态到mq
        movementScoreMQSend.sendMovementScore(userId, movement.getId(), MovementScoreMQSend.MOVEMENT_LIKE);

        // 5.返回点赞数量
        return ResponseEntity.ok(likeCount);

    }

    // 动态取消点赞
    public ResponseEntity removeMovementLike(String publishId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.调用rpc取消点赞
        Movement movement = movementService.findById(new ObjectId(publishId));
        Integer likeCount = commentService.removeComment(userId, movement.getUserId(), 1, publishId);
        // 3.移除redis高亮标记
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LIKE, publishId, userId));

        // 发动推荐动态到mq
        movementScoreMQSend.sendMovementScore(userId, movement.getId(), MovementScoreMQSend.MOVEMENT_DISLIKE);
        // 4.返回点赞数量
        return ResponseEntity.ok(likeCount);
    }

    // 动态喜欢
    public ResponseEntity setMovementLove(String publishId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis()); // 发表时间
        comment.setPublishId(new ObjectId(publishId));// 动态id
        comment.setCommentType(3);// 操作类型：喜欢
        comment.setUserId(userId); // 当前登录人id
        // 查询动态详情
        Movement movement = movementService.findById(comment.getPublishId());
        comment.setPublishUserId(movement.getUserId()); // 动态发布人id
        // 3.调用rpc保存
        Integer loveCount = commentService.saveComment(comment);
        // 4.向redis存储喜欢标记
        stringRedisTemplate.opsForValue().set(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, publishId, userId), "1");

        // 发动推荐动态到mq
        movementScoreMQSend.sendMovementScore(userId, movement.getId(), MovementScoreMQSend.MOVEMENT_LOVE);

        // 5.返回喜欢数量
        return ResponseEntity.ok(loveCount);

    }

    // 动态取消喜欢
    public ResponseEntity removeMovementLove(String publishId) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.调用rpc取消喜欢
        Movement movement = movementService.findById(new ObjectId(publishId));
        Integer loveCount = commentService.removeComment(userId, movement.getUserId(), 3, publishId);
        // 3.移除reids喜欢标记
        stringRedisTemplate.delete(StrUtil.format(ConstantUtil.MOVEMENT_LOVE, publishId, userId));

        // 发动推荐动态到mq
        movementScoreMQSend.sendMovementScore(userId, movement.getId(), MovementScoreMQSend.MOVEMENT_DISLOVE);
        // 4.返回喜欢数量
        return ResponseEntity.ok(loveCount);
    }

    // 单条动态（详情）
    public ResponseEntity findMovementVoById(String publishId) {
        // 1.调用rpc根据主键查询动态详情
        Movement movement = movementService.findById(new ObjectId(publishId));
        // 2.封装movmenetVo
        MovementVo movementVo = new MovementVo();
        UserInfo userInfo = userInfoService.findById(movement.getUserId());
        // 注意顺序：先userInfo  再 movement
        movementVo.setUserInfo(userInfo);
        movementVo.setMovement(movement);

        // 发动推荐动态到mq
        movementScoreMQSend.sendMovementScore(UserHolder.get().getId(), movement.getId(), MovementScoreMQSend.MOVEMENT_BROWSE);

        // 3.返回vo
        return ResponseEntity.ok(movementVo);
    }

    // 动态评论列表
    public ResponseEntity findMovementCommentByPage(String publishId, Integer pageNum, Integer pageSize) {
        // 1.调用rpc查询
        PageBeanVo pageBeanVo = commentService.findCommentByPage(publishId, pageNum, pageSize, 2);
        // 2.封装commentVo
        // 2-1 声明vo集合
        List<CommentVo> voList = new ArrayList<>();
        // 2-2 获取comment集合
        List<Comment> commentList = (List<Comment>) pageBeanVo.getItems();
        // 2-3 遍历comment集合
        if (CollectionUtil.isNotEmpty(commentList)) {
            for (Comment comment : commentList) {
                // 查询评论人的userInfo
                UserInfo userInfo = userInfoService.findById(comment.getUserId());

                //  创建vo
                CommentVo commentVo = new CommentVo();
                commentVo.setId(comment.getId().toHexString()); // 评论id
                commentVo.setAvatar(userInfo.getAvatar()); // 评论人头像
                commentVo.setNickname(userInfo.getNickname()); // 评论人昵称
                commentVo.setContent(comment.getContent()); // 评论内容
                commentVo.setCreateDate(DateUtil.formatDateTime(new Date(comment.getCreated()))); // 评论时间

                // 添加vo到集合中
                voList.add(commentVo);
            }
        }

        // 3.将vo设置到分页对象
        pageBeanVo.setItems(voList);

        // 4.返回分页对象
        return ResponseEntity.ok(pageBeanVo);
    }

    // 发表动态评论
    public void saveMovementComment(String publishId, String content) {
        // 1.获取线程内userId
        Long userId = UserHolder.get().getId();
        // 2.封装comment对象
        Comment comment = new Comment();
        comment.setCreated(System.currentTimeMillis());
        comment.setPublishId(new ObjectId(publishId));
        comment.setCommentType(2); // 操作类型：评论
        comment.setUserId(userId);
        Movement movement = movementService.findById(comment.getPublishId());
        comment.setPublishUserId(movement.getUserId());
        comment.setContent(content);
        // 发动推荐动态到mq
        movementScoreMQSend.sendMovementScore(userId, movement.getId(), MovementScoreMQSend.MOVEMENT_COMMENT);

        // 3.调用rpc保存评论
        commentService.saveComment(comment);
    }
}
